module shader.litshaderambientocclusion;

import render.render;
import scene.scene;
import scene.ray;
import scene.intersection;
import shader.environment;
import shader.abstractshader;
import std.math;
import utils.color;
import utils.vector3;
import utils.mt19937ar;

class LitShaderAmbientOcclusion: AbstractShader {
    const float SHADE_EPSILON = 0.01f;
    const int SAMPLE_COUNT = 100;

    private Environment mEnvironment;

    public bool skyhack;

    public void getColor(inout RenderContext context) {
        Vector3f x = context.rinters.hitpoint;
        Vector3f n = context.rinters.normal;
        RGBColor litCol;
        Ray secRay;
        for (int i = 0; i < SAMPLE_COUNT; i++) {
            float phi = 2.0f*PI*genrand_real1();
            float theta = skyhack
                ? PI*genrand_real1()-PI_2
                : PI_2*genrand_real1();
            secRay = Ray(x+n*SHADE_EPSILON,Vector3f.fromSpherical(theta,phi,1.0f),float.max);
            bool v = !context.scene.intersectShadowRay(secRay);
            if (v) {
                litCol = mEnvironment.getColor(theta,phi)*(1.0f/cast(float)SAMPLE_COUNT);
                context.addDirectionalLight(litCol, secRay.dir);
            }
        }
    }

    public void environment(Environment env) {
        mEnvironment = env;
    }

    public char[] toString() {
        return "Ambient Occlusion";
    }
}

